/**
 * ECSMatcher 性能测试套件
 * 
 * 用于验证优化效果，对比优化前后的性能差异
 */

import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";

/**
 * 性能测试配置
 */
interface TestConfig {
    name: string;              // 测试名称
    iterations: number;        // 迭代次数
    warmupIterations: number;  // 预热次数
}

/**
 * 测试结果
 */
interface TestResult {
    name: string;              // 测试名称
    totalTime: number;         // 总耗时（ms）
    avgTime: number;           // 平均耗时（ns）
    minTime: number;           // 最小耗时（ns）
    maxTime: number;           // 最大耗时（ns）
    opsPerSecond: number;      // 每秒操作数
}

/**
 * ECSMatcher 性能测试类
 */
export class ECSMatcherPerformanceTest {
    private static readonly DEFAULT_CONFIG: TestConfig = {
        name: '',
        iterations: 100000,        // 10万次迭代
        warmupIterations: 10000    // 1万次预热
    };

    /**
     * 运行所有性能测试
     */
    public static runAllTests(): void {
        console.log('='.repeat(80));
        console.log('ECSMatcher 性能测试开始');
        console.log('='.repeat(80));

        // 测试 1：单规则匹配
        this.testSingleRule();

        // 测试 2：双规则匹配
        this.testTwoRules();

        // 测试 3：三规则匹配
        this.testThreeRules();

        // 测试 4：多规则匹配
        this.testMultipleRules();

        // 测试 5：anyOf 匹配
        this.testAnyOf();

        // 测试 6：excludeOf 匹配
        this.testExcludeOf();

        // 测试 7：复杂组合匹配
        this.testComplexMatcher();

        // 测试 8：onlyOf 匹配（注意性能开销）
        this.testOnlyOf();

        // 测试 9：Matcher 克隆
        this.testClone();

        // 测试 10：key 生成
        this.testKeyGeneration();

        console.log('='.repeat(80));
        console.log('ECSMatcher 性能测试结束');
        console.log('='.repeat(80));
    }

    /**
     * 测试 1：单规则匹配（最常见）
     */
    private static testSingleRule(): void {
        // 创建测试组件
        @ecs.register('TestPosition1')
        class TestPosition1 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        // 创建实体
        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition1);

        // 创建 Matcher
        const matcher = ecs.Matcher.allOf(TestPosition1);

        // 运行测试
        const result = this.runTest('单规则匹配 (allOf)', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);

        // 清理
        entity.destroy();
    }

    /**
     * 测试 2：双规则匹配（常见）
     */
    private static testTwoRules(): void {
        @ecs.register('TestPosition2')
        class TestPosition2 extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        @ecs.register('TestVelocity2')
        class TestVelocity2 extends ecs.Comp {
            vx: number = 0;
            vy: number = 0;
        }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition2);
        entity.add(TestVelocity2);

        const matcher = ecs.Matcher.allOf(TestPosition2, TestVelocity2);

        const result = this.runTest('双规则匹配 (allOf + allOf)', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 3：三规则匹配（优化重点）
     */
    private static testThreeRules(): void {
        @ecs.register('TestPosition3')
        class TestPosition3 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity3')
        class TestVelocity3 extends ecs.Comp { vx: number = 0; }

        @ecs.register('TestHealth3')
        class TestHealth3 extends ecs.Comp { hp: number = 100; }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition3);
        entity.add(TestVelocity3);
        entity.add(TestHealth3);

        const matcher = ecs.Matcher.allOf(TestPosition3, TestVelocity3, TestHealth3);

        const result = this.runTest('三规则匹配 (allOf * 3)', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 4：多规则匹配（4+ 规则）
     */
    private static testMultipleRules(): void {
        @ecs.register('TestPosition4')
        class TestPosition4 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity4')
        class TestVelocity4 extends ecs.Comp { vx: number = 0; }

        @ecs.register('TestHealth4')
        class TestHealth4 extends ecs.Comp { hp: number = 100; }

        @ecs.register('TestDamage4')
        class TestDamage4 extends ecs.Comp { damage: number = 10; }

        @ecs.register('TestDefense4')
        class TestDefense4 extends ecs.Comp { defense: number = 5; }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition4);
        entity.add(TestVelocity4);
        entity.add(TestHealth4);
        entity.add(TestDamage4);
        entity.add(TestDefense4);

        const matcher = ecs.Matcher.allOf(TestPosition4, TestVelocity4, TestHealth4, TestDamage4, TestDefense4);

        const result = this.runTest('多规则匹配 (5个组件)', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 5：anyOf 匹配
     */
    private static testAnyOf(): void {
        @ecs.register('TestPosition5')
        class TestPosition5 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity5')
        class TestVelocity5 extends ecs.Comp { vx: number = 0; }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition5);

        const matcher = ecs.Matcher.anyOf(TestPosition5, TestVelocity5);

        const result = this.runTest('anyOf 匹配', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 6：excludeOf 匹配
     */
    private static testExcludeOf(): void {
        @ecs.register('TestPosition6')
        class TestPosition6 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestDead6')
        class TestDead6 extends ecs.Comp { }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition6);
        // 不添加 TestDead6

        const matcher = ecs.Matcher.allOf(TestPosition6).excludeOf(TestDead6);

        const result = this.runTest('excludeOf 匹配', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 7：复杂组合匹配
     */
    private static testComplexMatcher(): void {
        @ecs.register('TestPosition7')
        class TestPosition7 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity7')
        class TestVelocity7 extends ecs.Comp { vx: number = 0; }

        @ecs.register('TestHealth7')
        class TestHealth7 extends ecs.Comp { hp: number = 100; }

        @ecs.register('TestDead7')
        class TestDead7 extends ecs.Comp { }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition7);
        entity.add(TestVelocity7);
        entity.add(TestHealth7);

        const matcher = ecs.Matcher
            .allOf(TestPosition7, TestVelocity7)
            .allOf(TestHealth7)
            .excludeOf(TestDead7);

        const result = this.runTest('复杂组合匹配 (allOf + allOf + excludeOf)', () => {
            return matcher.isMatch(entity);
        });

        this.printResult(result);
        entity.destroy();
    }

    /**
     * 测试 8：onlyOf 匹配（性能开销大）
     */
    private static testOnlyOf(): void {
        @ecs.register('TestPosition8')
        class TestPosition8 extends ecs.Comp { x: number = 0; }

        const entity = ecs.createEntity() as ECSEntity;
        entity.add(TestPosition8);

        const matcher = ecs.Matcher.onlyOf(TestPosition8);

        const result = this.runTest('onlyOf 匹配 (⚠️ 性能开销大)', () => {
            return matcher.isMatch(entity);
        }, { iterations: 10000, warmupIterations: 1000, name: '' });

        this.printResult(result);
        console.log('  ⚠️  警告：onlyOf 性能开销大，不建议频繁使用');
        entity.destroy();
    }

    /**
     * 测试 9：Matcher 克隆
     */
    private static testClone(): void {
        @ecs.register('TestPosition9')
        class TestPosition9 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity9')
        class TestVelocity9 extends ecs.Comp { vx: number = 0; }

        const matcher = ecs.Matcher.allOf(TestPosition9, TestVelocity9);

        const result = this.runTest('Matcher 克隆', () => {
            const cloned = matcher.clone();
            return cloned !== null;
        });

        this.printResult(result);
    }

    /**
     * 测试 10：key 生成（缓存效果）
     */
    private static testKeyGeneration(): void {
        @ecs.register('TestPosition10')
        class TestPosition10 extends ecs.Comp { x: number = 0; }

        @ecs.register('TestVelocity10')
        class TestVelocity10 extends ecs.Comp { vx: number = 0; }

        const matcher = ecs.Matcher.allOf(TestPosition10, TestVelocity10);

        const result = this.runTest('key 生成（应被缓存）', () => {
            const key = matcher.key;
            return key.length > 0;
        });

        this.printResult(result);
        console.log('  ℹ️  首次生成后应被缓存，后续访问近乎 0 开销');
    }

    /**
     * 运行单个性能测试
     */
    private static runTest(
        name: string,
        testFn: () => boolean,
        config: Partial<TestConfig> = {}
    ): TestResult {
        const finalConfig = { ...this.DEFAULT_CONFIG, ...config, name };

        // 预热
        for (let i = 0; i < finalConfig.warmupIterations; i++) {
            testFn();
        }

        // 正式测试
        const times: number[] = [];
        const startTime = performance.now();

        for (let i = 0; i < finalConfig.iterations; i++) {
            const iterStart = performance.now();
            testFn();
            const iterEnd = performance.now();
            times.push((iterEnd - iterStart) * 1_000_000); // 转换为纳秒
        }

        const endTime = performance.now();
        const totalTime = endTime - startTime;

        // 计算统计信息
        const avgTime = times.reduce((a, b) => a + b, 0) / times.length;
        const minTime = Math.min(...times);
        const maxTime = Math.max(...times);
        const opsPerSecond = (finalConfig.iterations / totalTime) * 1000;

        return {
            name,
            totalTime,
            avgTime,
            minTime,
            maxTime,
            opsPerSecond
        };
    }

    /**
     * 打印测试结果
     */
    private static printResult(result: TestResult): void {
        console.log('-'.repeat(80));
        console.log(`测试：${result.name}`);
        console.log(`  总耗时：${result.totalTime.toFixed(2)} ms`);
        console.log(`  平均耗时：${result.avgTime.toFixed(2)} ns`);
        console.log(`  最小耗时：${result.minTime.toFixed(2)} ns`);
        console.log(`  最大耗时：${result.maxTime.toFixed(2)} ns`);
        console.log(`  吞吐量：${result.opsPerSecond.toFixed(0)} ops/s`);
        console.log('-'.repeat(80));
    }

    /**
     * 批量实体匹配测试
     */
    public static testBatchMatching(entityCount: number = 10000): void {
        console.log('='.repeat(80));
        console.log(`批量实体匹配测试（${entityCount} 个实体）`);
        console.log('='.repeat(80));

        // 创建测试组件
        @ecs.register('BatchTestPosition')
        class BatchTestPosition extends ecs.Comp {
            x: number = 0;
            y: number = 0;
        }

        @ecs.register('BatchTestVelocity')
        class BatchTestVelocity extends ecs.Comp {
            vx: number = 0;
            vy: number = 0;
        }

        @ecs.register('BatchTestHealth')
        class BatchTestHealth extends ecs.Comp {
            hp: number = 100;
        }

        // 创建实体
        const entities: ECSEntity[] = [];
        for (let i = 0; i < entityCount; i++) {
            const entity = ecs.createEntity() as ECSEntity;
            entity.add(BatchTestPosition);
            
            if (i % 2 === 0) {
                entity.add(BatchTestVelocity);
            }
            
            if (i % 3 === 0) {
                entity.add(BatchTestHealth);
            }
            
            entities.push(entity);
        }

        // 测试不同的 Matcher
        const matchers = [
            { name: 'allOf(Position)', matcher: ecs.Matcher.allOf(BatchTestPosition) },
            { name: 'allOf(Position, Velocity)', matcher: ecs.Matcher.allOf(BatchTestPosition, BatchTestVelocity) },
            { name: 'allOf(Position, Velocity, Health)', matcher: ecs.Matcher.allOf(BatchTestPosition, BatchTestVelocity, BatchTestHealth) },
            { name: 'allOf(Position).excludeOf(Health)', matcher: ecs.Matcher.allOf(BatchTestPosition).excludeOf(BatchTestHealth) }
        ];

        for (const { name, matcher } of matchers) {
            const startTime = performance.now();
            let matchCount = 0;

            for (const entity of entities) {
                if (matcher.isMatch(entity)) {
                    matchCount++;
                }
            }

            const endTime = performance.now();
            const totalTime = endTime - startTime;

            console.log('-'.repeat(80));
            console.log(`Matcher: ${name}`);
            console.log(`  匹配数量：${matchCount}/${entityCount}`);
            console.log(`  总耗时：${totalTime.toFixed(2)} ms`);
            console.log(`  平均耗时：${(totalTime * 1_000_000 / entityCount).toFixed(2)} ns/entity`);
            console.log(`  吞吐量：${(entityCount / totalTime * 1000).toFixed(0)} entities/s`);
        }

        // 清理
        for (const entity of entities) {
            entity.destroy();
        }

        console.log('='.repeat(80));
    }
}

/**
 * 使用示例
 */
export class ECSMatcherPerformanceExample {
    /**
     * 运行基本测试
     */
    public static runBasicTests(): void {
        ECSMatcherPerformanceTest.runAllTests();
    }

    /**
     * 运行批量测试
     */
    public static runBatchTests(): void {
        ECSMatcherPerformanceTest.testBatchMatching(10000);
        ECSMatcherPerformanceTest.testBatchMatching(50000);
        ECSMatcherPerformanceTest.testBatchMatching(100000);
    }

    /**
     * 运行完整测试套件
     */
    public static runFullTestSuite(): void {
        this.runBasicTests();
        console.log('\n\n');
        this.runBatchTests();
    }
}

// ============================================================================
// 使用方式
// ============================================================================

// 1. 运行基本测试
// ECSMatcherPerformanceExample.runBasicTests();

// 2. 运行批量测试
// ECSMatcherPerformanceExample.runBatchTests();

// 3. 运行完整测试套件
// ECSMatcherPerformanceExample.runFullTestSuite();

